package wsi.exp;

import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.rygh.core.html.Html;
import org.rygh.core.html.table.HtmlTable;
import org.rygh.core.html.table.TableData;
import org.rygh.core.html.table.TableTuple;
import org.rygh.core.util.UIo;
import org.rygh.core.util.UTime;
import org.rygh.core.util.timer.TaskTimeManager;
import org.rygh.core.xml.UXml;
import org.rygh.core.xml.XmlLeaf;
import org.rygh.core.xml.XmlObject;
import org.rygh.core.xml.XmlParser;
import org.rygh.core.xml.XmlPath;
import org.rygh.core.xml.XmlTree;

import wsi.exp.ExpXml.Tag;
import wsi.function.Function;
import wsi.script.AppConfig;

public class Exp4WebCallRatio extends Experiment {

	public static class Exp4Tuple {
		public int inputSize;
		public int webCalls;
		public long min;
		public long max;
		public double avg;

		public double getRatio() {
			return 1. * inputSize / webCalls;
		}

		public String toRatioString() {
			return String.format("%.2f", getRatio());
		}
	}

	public XmlTree getXmlTree(int inputSize, int webCall,
			TaskTimeManager manager) {
		XmlTree xml = new XmlTree();
		XmlLeaf parent;
		XmlObject obj;

		obj = new XmlObject(Tag.result.name());
		obj.addAttribute(Tag.experiment.name(), "4");
		obj.addAttribute(Tag.description.name(), "Web call ratio");
		obj.addAttribute(Tag.date.name(), UTime.toTodayString());

		parent = new XmlLeaf(xml.getRoot(), obj);

		obj = new XmlObject(Tag.input_size.name(), Integer.toString(inputSize));
		new XmlLeaf(parent, obj);

		obj = new XmlObject(Tag.web_call_count.name());
		obj.setValue(Integer.toString(webCall));
		new XmlLeaf(parent, obj);

		obj = new XmlObject(Tag.time.name());
		obj.addAttribute(
				Tag.min.name(),
				manager.getMin() == null ? "0" : Long.toString(manager.getMin()
						.duration()));
		obj.addAttribute(Tag.avg.name(), Double.toString(manager.getAvg()));
		obj.addAttribute(
				Tag.max.name(),
				manager.getMax() == null ? "0" : Long.toString(manager.getMax()
						.duration()));
		new XmlLeaf(parent, obj);

		return xml;
	}

	@Deprecated
	public void load4(File folder, Map<Function, Exp4Tuple> map) {
		for (File file : folder.listFiles()) {
			if (!file.getName().endsWith(".txt"))
				continue;

			String fname = UIo.getFileNameWithoutExtension(file.getName());
			Function function = parseFileName(fname);

			String content = UIo.readFile(file);

			String[] lines = content.split("\r\n");
			assert lines.length == 2 : fname;

			Exp4Tuple tuple = new Exp4Tuple();
			tuple.inputSize = Integer.parseInt(lines[0]);
			tuple.webCalls = Integer.parseInt(lines[1]);

			map.put(function, tuple);
		}
	}

	public void loadXml4(File folder, Map<Function, Exp4Tuple> map) {
		File[] files = folder.listFiles(UXml.XML_FILTER);
		assert files != null : folder.getAbsolutePath();

		for (File file : files) {
			String fname = UIo.getFileNameWithoutExtension(file.getName());
			Function function = parseFileName(fname);

			String content = UIo.readFile(file);
			XmlParser parser = new XmlParser(content);
			XmlTree xmltree = parser.parse();

			Exp4Tuple tuple = new Exp4Tuple();
			tuple.inputSize = Integer
					.parseInt(xmltree
							.getNodeByXPath(
									XmlPath.compose(Tag.result, Tag.input_size))
							.getValue().getValue());
			tuple.webCalls = Integer.parseInt(xmltree
					.getNodeByXPath(
							XmlPath.compose(Tag.result, Tag.web_call_count))
					.getValue().getValue());

			XmlObject timeObj = xmltree.getNodeByXPath(
					XmlPath.compose(Tag.result, Tag.time)).getValue();

			tuple.min = Long.parseLong(timeObj.getAttribute(Tag.min));
			tuple.max = Long.parseLong(timeObj.getAttribute(Tag.max));
			tuple.avg = Double.parseDouble(timeObj.getAttribute(Tag.avg));

			map.put(function, tuple);
		}
	}

	@Override
	public void compute() {

	}

	@Override
	public String save() {
		File exp = ExpFolderController.shared().getResultFolder();

		TableData data = new TableData();
		TableTuple tuple = new TableTuple();

		tuple.add("Web Service", "Function", "# Valid Inputs", "# Web Calls",
				"Ratio", "Min (ms)", "Avg (ms)", "Max (ms)");
		data.add(tuple);

		Map<Function, Exp4Tuple> map4 = new HashMap<>();
		File folder = ExpFolderController.shared().getFolderForExp4();

		loadXml4(folder, map4);

		for (Entry<Function, Exp4Tuple> e : map4.entrySet()) {
			Function function = e.getKey();
			Exp4Tuple t = e.getValue();

			tuple = new TableTuple();
			tuple.add(function.getService(), function.getName(), t.inputSize,
					t.webCalls);
			tuple.add(String.format("%.2f%%", 100. * t.inputSize / t.webCalls));

			tuple.add(t.min);
			tuple.add(String.format("%.2f", t.avg));
			tuple.add(t.max);
			data.add(tuple);
		}

		data.sort();

		//

		Html html = new Html("Experiment 4");
		html.addElement(AppConfig.shared().getConfigHtml());

		HtmlTable table = new HtmlTable("Experiment 4, Web Call Ratio", data);
		html.addElement(table);

		String htmlstr = html.toString();

		UIo.saveFile(new File(exp, ExpFolderController.EXP + "4_result.html"),
				htmlstr);

		return htmlstr;
	}
}
